package cn.chrilwe.pigpig.im.server.handler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;

import com.alibaba.fastjson.JSON;

import cn.chrilwe.pigpig.core.base.Code;
import cn.chrilwe.pigpig.core.base.ResMsg;
import cn.chrilwe.pigpig.im.config.ServerConfig;
import cn.chrilwe.pigpig.im.counter.RoomOnlineUserCounter;
import cn.chrilwe.pigpig.im.filters.Filter;
import cn.chrilwe.pigpig.im.protocol.TalkRequest;
import cn.chrilwe.pigpig.im.protocol.TalkResponse;
import cn.chrilwe.pigpig.im.server.WebSocketServer;
import cn.chrilwe.pigpig.im.service.ClientService;
import cn.chrilwe.pigpig.im.service.MessageDispatcherService;
import cn.chrilwe.pigpig.im.service.MessageService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

/**
 * 
 * @author chrilwe
 * 2020-7-26
 */
public class MessageHandler extends SimpleChannelInboundHandler<TalkRequest> {
	
	private static final String Channel = null;
	
	//channelId : channel
	public static Map<String, Channel> channels = new HashMap<String, Channel>();
	
	//roomId: map(clientId, channel)
	public static Map<String, Map> groupChannel = new HashMap<String,Map>();
	
	public static Map<String, String> channelIdAndRoomIdMap = new HashMap<String, String>();
	
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, TalkRequest msg) throws Exception {
		if(msg == null || msg.getRoomId() <= 0) {
			TalkResponse res = new TalkResponse();
			res.setStatus(Code.PROTOCOL_ERR);
			res.setResMsg(ResMsg.PROTOCOL_ERR);
			ChannelFuture cf = ctx.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(res)));
			boolean success = cf.isSuccess();
			if(success) {
				ctx.close();
			}
		} else {
			getOrSetGroupChannel(ctx, msg.getRoomId()+"");
			
			//执行过滤器
			TalkResponse response = invokeFilters(WebSocketServer.sortFilters,msg);
			
			//String clientId = ctx.channel().id().toString();
			//setClientDetail(msg.getRoomId()+"",clientId);
			
			MessageDispatcherService service = WebSocketServer.applicationContext.getBean(MessageDispatcherService.class);
			service.dispactcherMessage(groupChannel, msg, ctx);
		}
	}
	
	//客户端连接成功
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		String clientId = ctx.channel().id().toString();
		channels.put(clientId, ctx.channel());
	}
	
	
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		String channelId = ctx.channel().id().toString();
		channels.remove(channelId);
		String roomId = channelIdAndRoomIdMap.get(channelId);
		Map map = groupChannel.get(roomId);
		map.remove(channelId);
		
		RoomOnlineUserCounter counter = WebSocketServer.applicationContext.getBean(RoomOnlineUserCounter.class);
		counter.decr(roomId);
		
		ApplicationContext context = WebSocketServer.applicationContext;
		ClientService clientService = context.getBean(ClientService.class);
		clientService.closeConnect(roomId, channelId);
	}
	
	
	protected TalkResponse invokeFilters(List<Filter> sortFilters, TalkRequest talkRequest) {
		if(sortFilters.size() <= 0) {
			return null;
		}
		for(int i=0; i<sortFilters.size()-1; i++) {
			Filter filter = sortFilters.get(i);
			TalkResponse doChain = filter.doChain(talkRequest);
			if(doChain != null) {
				return doChain;
			}
		}
		return null;
	}
	
	@SuppressWarnings("rawtypes")
	protected void getOrSetGroupChannel(ChannelHandlerContext ctx, String roomId) {
		String clientId = ctx.channel().id().toString();
		groupChannel.put(roomId, channels);
		channelIdAndRoomIdMap.put(clientId, roomId);
		
		//房间人数加一
		RoomOnlineUserCounter counter = WebSocketServer.applicationContext.getBean(RoomOnlineUserCounter.class);
		counter.incr(roomId);
	}
	
	//redis中存放: hash集合(roomId: servername : JSON.toJSONString(clientIdList))
	/*
	 * protected void setClientDetail(String roomId, String clientId) {
	 * ApplicationContext context = WebSocketServer.applicationContext;
	 * StringRedisTemplate stringRedisTemplate =
	 * context.getBean(StringRedisTemplate.class); ServerConfig serverConfig =
	 * context.getBean(ServerConfig.class); String strList =
	 * (String)stringRedisTemplate.opsForHash().get(roomId,
	 * serverConfig.getServerName()); //TODO 待优化，如果在线人数过大，会造成内存溢出风险 List<String>
	 * clientIdList = null; if(StringUtils.isNotEmpty(strList)) { clientIdList =
	 * JSON.parseArray(strList, String.class); boolean contains =
	 * clientIdList.contains(clientId); if(!contains) { clientIdList.add(clientId);
	 * } } else { clientIdList = new ArrayList<String>();
	 * clientIdList.add(clientId); } stringRedisTemplate.opsForHash().put(roomId,
	 * serverConfig.getServerName(), JSON.toJSONString(clientIdList)); }
	 */
}
